package com.asamioffice.goldenport.servlet;

import java.io.*;
import java.security.Principal;
import java.util.*;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletInputStream;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

/**
 * @since   Sep. 21, 2010
 * @version Apr. 10, 2011
 * @author  ASAMI, Tomoharu
 */
public class StubServletRequest implements HttpServletRequest {
    public String method = "GET";
    public Map<String, String> parameters = new LinkedHashMap<String, String>();
    public List<Cookie> cookies= new ArrayList<Cookie>();
    public Map<String, String> headers = new LinkedHashMap<String, String>();
    public Map<String, String> attributes = new LinkedHashMap<String, String>();
    public String protocol = "HTTP/1.1";
    public String scheme = "http";
    public String serverName = "undefined";
    public String contextPath = "/contextPath";
    public String servletPath = "/servletPath";
    public String pathInfo = "/";
    public String authType = null;
    public String encoding = null;
    public String contentType = null;
    public int contentLength = 0;
    private String _content_string = null;
    private byte[] _content_binary = null;

    @Override
    public String getMethod() {
        return method;
    }

    public void setMethod(String method) {
        this.method = method;
    }

    @Override
    public String getAuthType() {
        return authType;
    }

    @Override
    public String getPathInfo() {
        System.out.println("StubServletRequest#getPathInfo = " + pathInfo);
        return pathInfo;
    }

    @Override
    public String getServletPath() {
        return servletPath;
    }

    @Override
    public String getContextPath() {
        return contextPath;
    }

    @Override
    public String getRequestURI() {
        StringBuilder buf = new StringBuilder();
        buf.append(contextPath);
        if (contextPath.endsWith("/")) {
            if (servletPath.startsWith("/")) {
                buf.append(servletPath.substring(1));
            } else {
                buf.append(servletPath);
            }
        } else {
            buf.append(servletPath);
        }
        if (servletPath.endsWith("/")) {
            if (pathInfo.startsWith("/")) {
                buf.append(pathInfo.substring(1));
            } else {
                buf.append(pathInfo);
            }
        } else {
            buf.append(pathInfo);
        }
        System.out.println("StubServletRequest#getRequestURI = " + buf.toString());
        return buf.toString();
    }

    @Override
    public StringBuffer getRequestURL() {
        StringBuffer buf = new StringBuffer();
        buf.append(scheme);
        buf.append("://");
        buf.append(serverName);
        buf.append(getRequestURI());
        System.out.println("StubServletRequest#getRequestURL = " + buf.toString());
        return buf;
    }

    @Override
    public String getPathTranslated() {
        throw new UnsupportedOperationException();
    }

    @Override
    public String getProtocol() {
        throw new UnsupportedOperationException();
    }

    @Override
    public String getScheme() {
        return scheme;
    }

    @Override
    public String getServerName() {
        return serverName;
    }

    @Override
    public int getServerPort() {
        throw new UnsupportedOperationException();
    }

    @Override
    public String getRemoteUser() {
        throw new UnsupportedOperationException();
    }

    @Override
    public String getLocalAddr() {
        throw new UnsupportedOperationException();
    }

    @Override
    public String getLocalName() {
        throw new UnsupportedOperationException();
    }

    @Override
    public int getLocalPort() {
        throw new UnsupportedOperationException();
    }

    @Override
    public String getQueryString() {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public Cookie[] getCookies() {
        return cookies.toArray(new Cookie[cookies.size()]);
    }

    @Override
    public Enumeration getHeaderNames() {
        return Collections.enumeration(headers.keySet());
    }

    @Override
    public String getHeader(String name) {
        return headers.get(name);
    }

    @Override
    public int getIntHeader(String name) {
        throw new UnsupportedOperationException();
    }

    @Override
    public long getDateHeader(String name) {
        throw new UnsupportedOperationException();
    }

    @Override
    public Enumeration getHeaders(String name) {
        throw new UnsupportedOperationException();
    }

    @Override
    public HttpSession getSession() {
        throw new UnsupportedOperationException();
    }

    @Override
    public HttpSession getSession(boolean value) {
        throw new UnsupportedOperationException();
    }

    @Override
    public String getRequestedSessionId() {
        throw new UnsupportedOperationException();
    }

    @Override
    public boolean isRequestedSessionIdFromCookie() {
        throw new UnsupportedOperationException();
    }

    @Override
    public boolean isRequestedSessionIdFromURL() {
        throw new UnsupportedOperationException();
    }

    @Override
    public boolean isRequestedSessionIdFromUrl() {
        throw new UnsupportedOperationException();
    }

    @Override
    public boolean isRequestedSessionIdValid() {
        throw new UnsupportedOperationException();
    }

    @Override
    public Principal getUserPrincipal() {
        throw new UnsupportedOperationException();
    }

    @Override
    public boolean isUserInRole(String value) {
        throw new UnsupportedOperationException();
    }

    @Override
    public Enumeration getAttributeNames() {
        throw new UnsupportedOperationException();
    }

    @Override
    public Object getAttribute(String name) {
        throw new UnsupportedOperationException();
    }

    @Override
    public void setAttribute(String name, Object value) {
        throw new UnsupportedOperationException();
    }

    @Override
    public void removeAttribute(String name) {
        throw new UnsupportedOperationException();
    }

    @Override
    public String getCharacterEncoding() {
        return encoding;
    }

    @Override
    public void setCharacterEncoding(String encoding)
            throws UnsupportedOperationException {
        this.encoding = encoding;
    }

    @Override
    public String getContentType() {
        return contentType;
    }

    @Override
    public int getContentLength() {
        return 0;
    }

    @Override
    public ServletInputStream getInputStream() throws IOException {
        if (_content_binary != null) {
            return new BinaryServletInputStream(_content_binary);
        } else if (_content_string != null) {
            return new StringServleteInputStream(_content_string, _get_encoding());
        } else {
            return new BinaryServletInputStream(new byte[0]);
        }
    }

    @Override
    public BufferedReader getReader() throws IOException {
        if (_content_string != null) {
            return new BufferedReader(new StringReader(_content_string));
        } else {
            String enc = _get_encoding();
            return new BufferedReader(new InputStreamReader(getInputStream(), enc));
        }
    }

    private String _get_encoding() {
        return encoding != null ? encoding : "utf-8";
    }

    @Override
    public Locale getLocale() {
        throw new UnsupportedOperationException();
    }

    @Override
    public Enumeration getLocales() {
        throw new UnsupportedOperationException();
    }

    @Override
    public String getParameter(String name) {
        return parameters.get(name);
    }

    @Override
    public Map getParameterMap() {
        return parameters;
    }

    @Override
    public Enumeration getParameterNames() {
        return Collections.enumeration(parameters.keySet());
    }

    @Override
    public String[] getParameterValues(String name) {
        String value = getParameter(name);
        if (value == null) {
            return null;
        } else {
            return new String[] { value };
        }
    }

    @Override
    public String getRealPath(String path) {
        throw new UnsupportedOperationException();
    }

    @Override
    public String getRemoteAddr() {
        throw new UnsupportedOperationException();
    }

    @Override
    public String getRemoteHost() {
        throw new UnsupportedOperationException();
    }

    @Override
    public int getRemotePort() {
        throw new UnsupportedOperationException();
    }

    @Override
    public RequestDispatcher getRequestDispatcher(String arg0) {
        throw new UnsupportedOperationException();
    }

    @Override
    public boolean isSecure() {
        throw new UnsupportedOperationException();
    }

    public void setContent(String contenttype, String string) {
        this.contentType = contenttype;
        _content_string = string;
    }

    // 2011.4.7
    class BinaryServletInputStream extends ServletInputStream {
        private final byte[] _binary;
        private int _offset = 0;

        BinaryServletInputStream(byte[] binary) {
            _binary = binary;
        }

        public int read() {
            if (_offset >= _binary.length) return -1;
            else return _binary[_offset++];
        }
    }

    // 2011.4.7
    class StringServleteInputStream extends BinaryServletInputStream {
        StringServleteInputStream(String string, String encoding) throws IOException {
            super(string.getBytes(encoding));
        }
    }
}
